""" Utility functions related to django storages """
import logging

from typing import Optional, List
from django.conf import settings
from django.core.files.storage import storages
from django.utils.module_loading import import_string


logger = logging.getLogger(__name__)


def resolve_storage_backend(
        storage_key: str,
        legacy_setting_key: str,
        legacy_sec_setting_keys: List[str] = None,
        options: Optional[dict] = None):
    """
    Configures and returns a Django `Storage` instance, compatible with both Django 4 and Django 5.
    Params:
        storage_key = The key name saved in Django storages settings.
        legacy_setting_key = The key name saved in Django settings.
        legacy_sec_setting_keys = List of keys to get the storage class.
            For legacy dict settings like settings.BLOCK_STRUCTURES_SETTINGS.get('STORAGE_CLASS'),
            it is necessary to access a second-level key or above to retrieve the class path.
        options = Kwargs for the storage class.
    Returns:
        An instance of the configured storage backend.
    Raises:
        ImportError: If the specified storage class cannot be imported.
        KeyError: If the specified key is not found in the legacy settings.
    Main goal:
        Deprecate the use of `django.core.files.storage.get_storage_class`.
    How:
        Replace `get_storage_class` with direct configuration logic,
        ensuring backward compatibility with both Django 4 and Django 5 storage settings.
    """

    storage_path = getattr(settings, legacy_setting_key, None)
    storages_config = getattr(settings, 'STORAGES', {})
    options = options or {}

    if storage_key in storages_config:
        # Use case 1: STORAGES is defined
        # If STORAGES is present, we retrieve it through the storages API
        # settings.py must define STORAGES like:
        # STORAGES = {
        #     "default": {"BACKEND": "...", "OPTIONS": {...}},
        #     "custom": {"BACKEND": "...", "OPTIONS": {...}},
        # }
        # See: https://docs.djangoproject.com/en/5.2/ref/settings/#std-setting-STORAGES
        return storages[storage_key]

    # Use case 2: Legacy settings
    # Fallback to import the storage_path (Obtained from django settings) manually
    if isinstance(storage_path, dict) and legacy_sec_setting_keys:
        # If storage_path is a dict, we need to access the second-level keys
        # to retrieve the storage class path.
        # This is useful for legacy settings that store storage paths in a nested structure.
        for deep_setting_key in legacy_sec_setting_keys:
            # For legacy dict settings like settings.CUSTOM_STORAGE = {"BACKEND": "cms.custom.."}
            if deep_setting_key not in storage_path:
                logger.warning(
                    f"Key {legacy_setting_key} '{deep_setting_key}' not found in storage settings {storage_path}."
                    "Using default storage path."
                )
                storage_path = None  # We set it to None to use the default storage later
                break
            storage_path = storage_path.get(deep_setting_key)

    StorageClass = import_string(storage_path or storages_config["default"]["BACKEND"])
    return StorageClass(**options)
